package traveldream.ejb.sessionBean;

import java.util.ArrayList;
import java.util.Calendar;
import java.util.Date;
import java.util.List;

import javax.ejb.EJB;
import javax.ejb.Stateless;
import javax.faces.context.ExternalContext;
import javax.faces.context.FacesContext;
import javax.persistence.EntityManager;
import javax.persistence.PersistenceContext;
import javax.persistence.Query;

import traveldream.ejb.DTO.BookingDTO;
import traveldream.ejb.DTO.ExcursionDTO;
import traveldream.ejb.DTO.GiftListDTO;
import traveldream.ejb.DTO.HotelDTO;
import traveldream.ejb.DTO.PackageDTO;
import traveldream.ejb.DTO.TransportationDTO;
import traveldream.ejb.entities.Booking;
import traveldream.ejb.entities.DefaultPackage;
import traveldream.ejb.entities.Excursion;
import traveldream.ejb.entities.GiftList;
import traveldream.ejb.entities.Hotel;
import traveldream.ejb.entities.TransportationMean;
import traveldream.ejb.entities.User;
import traveldream.ejb.interfaces.GiftListBeanLocal;
import traveldream.ejb.interfaces.NotFindException;
import traveldream.ejb.interfaces.PackagePurchaseBeanLocal;

/**
 * Session Bean implementation class GiftListBean
 */
@Stateless
public class GiftListBean implements GiftListBeanLocal {

	@EJB
	PackagePurchaseBeanLocal packagePurchaseBeanLocal;
	
	@PersistenceContext
	private EntityManager em;
    /**
     * Default constructor. 
     */
    public GiftListBean() {
        // TODO Auto-generated constructor stub
    }

	@Override
	public void createGiftList(PackageDTO pDTO,int n) {
		GiftList gl = new GiftList();
		FacesContext context = FacesContext.getCurrentInstance();
        ExternalContext externalContext = context.getExternalContext();
        String user = externalContext.getUserPrincipal().getName();
        User u = em.find(User.class, user);
		gl.setEMail_Customer(u);
		gl.setDescription(pDTO.getDescription());
		gl.setName(pDTO.getName());
		gl.setNation(pDTO.getNation());
		gl.setHotel(em.find(Hotel.class, pDTO.getIdHotel()));
    	gl.setReturn(em.find(TransportationMean.class, pDTO.getIdReturn()));
    	gl.setGoing(em.find(TransportationMean.class, pDTO.getIdGoing()));
    	gl.setInvalid(false);
    	int difference = (int) dayBetweenTwoDate(gl.getGoing().getArrival_Date(),gl.getReturn().getDeparture_Date());
    	int price = n*difference*gl.getHotel().getPrice();  //(gl.getReturn().getDeparture_Date() - gl.getGoing().getArrival_Date())*gl.getHotel().getPrice();
    	gl.setPriceHotel(price);
    	gl.setExcursion(em.find(Excursion.class, pDTO.getIdExcursion()));
    	em.persist(gl);
	}

	public long dayBetweenTwoDate(Date uno, Date due) {
		Calendar c1 = Calendar.getInstance();
		Calendar c2 = Calendar.getInstance();
		c1.setTime(uno);
		c2.setTime(due);

		long giorni = (c2.getTime().getTime() - c1.getTime()
				.getTime())	/ (24 * 3600 * 1000);

		return giorni;
	}


	
	@Override
	public List<GiftListDTO> allPackage() {
		FacesContext context = FacesContext.getCurrentInstance();
        ExternalContext externalContext = context.getExternalContext();
        String user = externalContext.getUserPrincipal().getName();
        User u = em.find(User.class, user);
		Query query= em.createNamedQuery("GiftList.findAll");
		query.setParameter("user", u);
		List<GiftList> gl=query.getResultList();
    	List<GiftListDTO> glDTO = new ArrayList<GiftListDTO>();
    	
    	for(GiftList g : gl){
    		glDTO.add(g.convertToDTO());
    	}
    	return glDTO;
	}

	@Override
	public GiftListDTO find(int passedParameter) throws NotFindException{
		// TODO Auto-generated method stub
		GiftList gl=em.find(GiftList.class, passedParameter);
		try{
		return gl.convertToDTO();
		}
		catch(NullPointerException e){
			throw new NotFindException();
		}
	}

	@Override
	public boolean purchaseHotel(GiftListDTO viewedP) throws NotFindException{
		GiftList gl = em.find(GiftList.class, viewedP.getId());
		try{
		if(gl.getBuyer_Hotel() != null){
			return false;
		}
		}
		catch(NullPointerException e){
			throw new NotFindException();
		}
		
		//take the actual user
		FacesContext context = FacesContext.getCurrentInstance();
        ExternalContext externalContext = context.getExternalContext();
        String user = externalContext.getUserPrincipal().getName();
        User u = em.find(User.class, user);
        
        gl.setBuyer_Hotel(u);
        em.merge(gl);
        
        //TODO: check booking 
        addBooking(gl);
		return true;
	}

	@Override
	public boolean purchaseGoing(GiftListDTO viewedP) throws NotFindException{
		GiftList gl = em.find(GiftList.class, viewedP.getId());
		try{
		if(gl.getBuyer_Going() != null){
			return false;
		}
		}
		catch(NullPointerException e){
			throw new NotFindException();
		}
		//take the actual user
		FacesContext context = FacesContext.getCurrentInstance();
        ExternalContext externalContext = context.getExternalContext();
        String user = externalContext.getUserPrincipal().getName();
        User u = em.find(User.class, user);
        
        gl.setBuyer_Going(u);
        em.merge(gl);
        
        //TODO: check booking 
        addBooking(gl);
		return true;
	}

	@Override
	public boolean purchaseReturn(GiftListDTO viewedP) throws NotFindException{
		GiftList gl = em.find(GiftList.class, viewedP.getId());
		try{
		if(gl.getBuyer_Return() != null){
			return false;
		}
		}
		catch(NullPointerException e){
			throw new NotFindException();
		}
		//take the actual user
		FacesContext context = FacesContext.getCurrentInstance();
        ExternalContext externalContext = context.getExternalContext();
        String user = externalContext.getUserPrincipal().getName();
        User u = em.find(User.class, user);
        
        gl.setBuyer_Return(u);
        em.merge(gl);
        
        //TODO: check booking 
        addBooking(gl);
		return true;
	}

	@Override
	public boolean purchaseExcursion(GiftListDTO viewedP) throws NotFindException{
		GiftList gl = em.find(GiftList.class, viewedP.getId());
		try{
		if(gl.getBuyer_Excursion() != null){
			return false;
		}
		}
		catch(NullPointerException e){
			throw new NotFindException();
		}
		//take the actual user
		FacesContext context = FacesContext.getCurrentInstance();
        ExternalContext externalContext = context.getExternalContext();
        String user = externalContext.getUserPrincipal().getName();
        User u = em.find(User.class, user);
        gl.setBuyer_Excursion(u);
        em.merge(gl);
        
        //TODO: check booking 
        addBooking(gl);
		return true;
	}
	
	private void addBooking(GiftList gl){
		if(gl.getBuyer_Hotel()==null)
			return;
		if(gl.getBuyer_Going()==null)
			return;
		if(gl.getBuyer_Return()==null)
			return;
		if(gl.getExcursion()!=null)
			if(gl.getBuyer_Excursion()==null)
				return;
		BookingDTO bDTO = genBDTO(gl);
		Excursion e=gl.getExcursion();
		ExcursionDTO eDTO=null;
		if(e!=null)
			eDTO=e.convertToDTO();
		packagePurchaseBeanLocal.booking(bDTO, eDTO);
	}

	@Override
	public boolean checkAvailability(GiftListDTO viewedP) {
		// TODO Auto-generated method stub
		GiftList gl;
		gl=convertFromDTO(viewedP);
		BookingDTO bDTO = genBDTO(gl);
		Excursion e=gl.getExcursion();
		ExcursionDTO eDTO=null;
		if(e!=null)
			eDTO=e.convertToDTO();
		 if(packagePurchaseBeanLocal.checkAvailability(bDTO, eDTO))
			 return true;
		 gl.setInvalid(true);
		 em.merge(gl);
		 return false;
	}
	
	private BookingDTO genBDTO(GiftList gl){
		Hotel h=gl.getHotel();
		HotelDTO hDTO=h.convertToDTO();
		BookingDTO bDTO=new BookingDTO();
		bDTO.sethDTO(hDTO);
		TransportationMean g=gl.getGoing();
		TransportationDTO goDTO=g.convertToDTO();
		bDTO.setgDTO(goDTO);
		TransportationMean r=gl.getReturn();
		TransportationDTO rDTO=r.convertToDTO();
		bDTO.setrDTO(rDTO);
		int giorni = (int) dayBetweenTwoDate(goDTO.getArrivalDate(), rDTO.getDepartureDate());
		bDTO.setnOfPeople(gl.getPriceHotel()/(hDTO.getPrice()*giorni));
		return bDTO;
	}
	
	public GiftList convertFromDTO(GiftListDTO viewedP){
		GiftList gl=new GiftList();
		gl.setId(viewedP.getId());
		gl.setEMail_Customer(em.find(User.class, viewedP.getOwner()));
		gl.setDescription(viewedP.getDescription());
		gl.setName(viewedP.getName());
		gl.setNation(viewedP.getNation());
		gl.setHotel(em.find(Hotel.class, viewedP.getIdHotel()));
    	gl.setReturn(em.find(TransportationMean.class, viewedP.getIdReturn()));
    	gl.setGoing(em.find(TransportationMean.class, viewedP.getIdGoing()));
    	gl.setPriceHotel(viewedP.getPriceHotel());
    	gl.setExcursion(em.find(Excursion.class, viewedP.getIdExcursion()));
    	if(viewedP.getBuyerHotel()!=null)
    		gl.setBuyer_Hotel(em.find(User.class,viewedP.getBuyerHotel()));
    	if(viewedP.getBuyerGoing()!=null)
    		gl.setBuyer_Going(em.find(User.class,viewedP.getBuyerGoing()));
    	if(viewedP.getBuyerReturn()!=null)
    		gl.setBuyer_Return(em.find(User.class,viewedP.getBuyerReturn()));
    	if(viewedP.getBuyerExcursion()!=null)
    		gl.setBuyer_Excursion(em.find(User.class,viewedP.getBuyerExcursion()));
    	return gl;
	}
}
